package minimax;

import java.util.Iterator;
import java.util.Vector;




import problem.Heuristic;
import problem.logic;
import agents.AgentImpl;
import env.City;
import env.Move;
import env.World;

public class MoveNode_C {
	public String toString(int level) {
		String ans;
		if(moveToHere!=null)
			ans = moveToHere.toString();
		else
			ans = "no-op";
		ans+="\n";
		if(sons.isEmpty())
			return ans+Heuristic.fullCooperativeHeuristic(copiedWorld, friend, foe)+"terminal\n";
		else
		{
		Iterator<MoveNode_C> it = sons.iterator();
		while(it.hasNext())
			{
			for(int i=0;i<level;i++)
				ans+="#"+level;
			MoveNode_C son = it.next(); 
			ans+=" ("+(son.cost_friend+son.cost_foe)+") "+son.toString(level+1);
			}
		}
		return ans;
	}
	@Override
	public String toString() {
		
		return this.toString(1);
	}

	public World copiedWorld;
	public Move moveToHere;
	public Vector<MoveNode_C> sons;
	public MoveNode_C parent;
	public int cost_friend;
	public int cost_foe;
	public int node_cost;
	public int depth;
	public int moveToHereCost;
	public AgentImpl friend;
	public AgentImpl foe;

	public MoveNode_C(World world, Move moveToHere, MoveNode_C parent,  AgentImpl friend, AgentImpl foe) 
	{
		super();
		sons = new Vector<MoveNode_C>();
		this.copiedWorld = new World(world);
		this.moveToHere = moveToHere;
//		if(moveToHere!=null &&(moveToHere.chems==true && moveToHere.to.getName().equals("3")))
//			System.out.println(friend.goals+"GOAL");
		moveToHereCost = copiedWorld.moveAgents(moveToHere);
		this.parent = parent;
		
		//TODO this may have to be replaced with copy
		this.friend=friend;
		this.foe=foe;
		
		
		if (parent==null)
		{
			cost_friend=0;
			cost_foe=0;
			depth=main.Main.cutoff;
//			moveToHere=Minimax_decide();
		}
		else
		{
			depth=parent.depth-1;
			cost_friend=parent.cost_friend;
			cost_foe=parent.cost_foe;
		}
	}

	public Move Minimax_decide() 
	{
		
		Vector<Move> possibleMoves = copiedWorld.possibleMoves(friend, copiedWorld.getCityByName(friend.currentCityName())); //add documentation
		Iterator<Move> it = possibleMoves.iterator();
		Move ans=null;
		int temp_cost=Integer.MAX_VALUE;
		while (it.hasNext())
		{
			Move move = it.next();
			City friendCurrent = friend.current;
			City foeCurrent = foe.current;
			MoveNode_C new_moveNode = new MoveNode_C(copiedWorld, move, this, friend, foe);
			
			sons.add(new_moveNode);
//			if(ans==null)
//			{
//				ans = new_moveNode.moveToHere;
//				temp_cost = new_moveNode.min_value(Integer.MAX_VALUE);
//			}
//			else
//			{
				int new_cost = new_moveNode.min_value_foe(temp_cost);
				friend.setCurrentCity(friendCurrent);
				foe.setCurrentCity(foeCurrent);
				
//				if(new_moveNode.moveToHere!=null)
//					System.out.println(new_moveNode.moveToHere.toString()+new_cost);
//				else
//					System.out.println("no-op "+new_cost);
				if(temp_cost>new_cost)
				{
					ans=new_moveNode.moveToHere;
					temp_cost=new_cost;
				}
			//}
		}
		
//			System.out.println(this);
			return ans;
	}

//	private int max_value(int prune_cost) 
//	{
//		
//		cost_foe+=moveToHereCost;
//		if(depth==0)
////			return Integer.MAX_VALUE;
//		return cost_friend-cost_foe;
////			return Heuristic.zeroSumHeuristic(copiedWorld, friend, foe);
//		if(copiedWorld.allDone())
//		{
////			System.out.println("GOAL");
//			return cost_friend-cost_foe;
//		}
//			
//		int temp_cost=Integer.MAX_VALUE;
//		Vector<Move> possibleMoves;
//		
////			possibleMoves = copiedWorld.possibleMoves(friend, moveToHere.to); //add documentation
//			possibleMoves = copiedWorld.possibleMoves(friend, copiedWorld.getCityByName(friend.currentCityName())); //add documentation
//		Iterator<Move> it = possibleMoves.iterator();
//		while (it.hasNext())
//		{
//			Move move = it.next();
//			City friendCurrent = friend.current;
//			City foeCurrent = foe.current;
//			MoveNode_C new_moveNode = new MoveNode_C(copiedWorld, move, this, friend, foe);
//			
//			
//			sons.add(new_moveNode);
//			temp_cost=Math.min(temp_cost, new_moveNode.min_value_foe(temp_cost));
//			friend.setCurrentCity(friendCurrent);
//			foe.setCurrentCity(foeCurrent);
//			if(temp_cost<=prune_cost)
//				return temp_cost;
//		}
//			
//		//return Math.max(temp_cost,cost_friend-cost_foe+main.Main.noOpCost);
//		return temp_cost;
//	}

	private int min_value_friend(int prune_cost) 
	{
		cost_foe+=moveToHereCost;
		if(depth==0)
//			return Integer.MAX_VALUE;
			return cost_friend+cost_foe;
//			return Heuristic.zeroSumHeuristic(copiedWorld, foe, friend); //this is reversed because we need to estimate the move by the opponent
//			return cost_friend+cost_foe+Heuristic.fullCooperativeHeuristic(copiedWorld, friend, foe);
		if(copiedWorld.allDone())
		{
//			System.out.println("GOAL");
			return cost_friend+ cost_foe;
			
		}
		int temp_cost=Integer.MAX_VALUE;
		Vector<Move> possibleMoves; 
		
//			possibleMoves = copiedWorld.possibleMoves(friend, moveToHere.to); //add documentation
		
			possibleMoves = copiedWorld.possibleMoves(friend, copiedWorld.getCityByName(friend.currentCityName())); //add documentation
		Iterator<Move> it = possibleMoves.iterator();
		while (it.hasNext())
		{
			Move move = it.next();
			City friendCurrent = friend.current;
			City foeCurrent = foe.current;
			MoveNode_C new_moveNode = new MoveNode_C(copiedWorld, move, this, friend, foe);
			
			sons.add(new_moveNode);
			temp_cost=Math.min(temp_cost, new_moveNode.min_value_foe(temp_cost));
			friend.setCurrentCity(friendCurrent);
			foe.setCurrentCity(foeCurrent);
//			if(temp_cost>=prune_cost)
//				return temp_cost;
		}
			
		//return Math.min(temp_cost,cost_friend-cost_foe+main.Main.noOpCost);
		return temp_cost;
	}
	
	private int min_value_foe(int prune_cost) 
	{
		cost_friend+=moveToHereCost;
		if(depth==0)
//			return Integer.MAX_VALUE;
			return cost_friend+cost_foe;
//			return cost_friend+cost_foe+Heuristic.fullCooperativeHeuristic(copiedWorld, friend, foe);
//			return Heuristic.zeroSumHeuristic(copiedWorld, foe, friend); //this is reversed because we need to estimate the move by the opponent
		if(copiedWorld.allDone())
		{
//			System.out.println("GOAL");
			return cost_friend+ cost_foe;
			
		}
		int temp_cost=Integer.MAX_VALUE;
		Vector<Move> possibleMoves; 
		
//			possibleMoves = copiedWorld.possibleMoves(friend, moveToHere.to); //add documentation
		
			possibleMoves = copiedWorld.possibleMoves(foe, copiedWorld.getCityByName(foe.currentCityName())); //add documentation
		Iterator<Move> it = possibleMoves.iterator();
		while (it.hasNext())
		{
			Move move = it.next();
			City friendCurrent = friend.current;
			City foeCurrent = foe.current;
			MoveNode_C new_moveNode = new MoveNode_C(copiedWorld, move, this, friend, foe);
			
			sons.add(new_moveNode);
			temp_cost=Math.min(temp_cost, new_moveNode.min_value_friend(temp_cost));
			friend.setCurrentCity(friendCurrent);
			foe.setCurrentCity(foeCurrent);
//			if(temp_cost>=prune_cost)
//				return temp_cost;
		}
			
		//return Math.min(temp_cost,cost_friend-cost_foe+main.Main.noOpCost);
		return temp_cost;
	}
}
